<!-- 上传文件组件 -->
<template>
	<view @imgList="imgList" style="margin-left: 20rpx;">
		<u-upload :fileList="fileList1.length === 0 ? files : fileList1" :sizeType="sizeType" @afterRead="afterRead"
			@delete="deletePic" name="1" :maxCount="8" multiple :max-size="20 * 1024 * 1024" :previewFullImage="true"
			:limitType="limitType" @oversize="oversize" @clickPreview="clickPreview" width="70" height="70"
			:disabled="isdisabled" :deletable="deletable">
			<!-- <image v-show="!isdisabled" src="@/static/images/med-icon/u24719.png"></image> -->
		</u-upload>
	</view>
</template>
 
<script>
	/**
	 * 图片压缩
	 * imgSrc 地址
	 * scale 压缩质量 0-1
	 * type 文件类型
	 */
	const compressImg = (imgSrc, scale, type, callback) => {
		// uni.$u.toast('压缩中')
		var img = new Image();
		img.src = imgSrc;
		img.onload = function() {
			var that = this;
			var h = (img.height * scale).toFixed(0); // 默认按质量比例压缩
			var w = (img.width * scale).toFixed(0);
			var canvas = document.createElement('canvas');
			var ctx = canvas.getContext('2d');
			var width = document.createAttribute("width");
			width.nodeValue = w;
			var height = document.createAttribute("height");
			height.nodeValue = h;
			canvas.setAttributeNode(width);
			canvas.setAttributeNode(height);
			ctx.drawImage(that, 0, 0, w, h);
			var base64 = canvas.toDataURL('image/jpeg', scale); //压缩比例
			canvas = null;
			if (type == 'base64') {
				let data = {
					size: getBase64Size(base64),
					type: type,
					source: base64
				}
				callback(base64);
			} else {
				let blob = base64ToBlob(base64);
				console.log('压缩后的大小', blob.size);
				const blobUrl = window.URL.createObjectURL(blob); //blob地址					
				blob.source = blobUrl
				callback(blob);
			}
		}
	};
	/**base转Blob */
	const base64ToBlob = (base64) => {
		var arr = base64.split(','),
			mime = arr[0].match(/:(.*?);/)[1],
			bstr = atob(arr[1]),
			n = bstr.length,
			u8arr = new Uint8Array(n);
		while (n--) {
			u8arr[n] = bstr.charCodeAt(n);
		}
		return new Blob([u8arr], {
			type: mime
		});
	};
	/**获取base64的文件大小 */
	const getBase64Size = () => {
		let size = 0;
		if (base64Str) { // 获取base64图片byte大小
			const equalIndex = base64Str.indexOf('='); // 获取=号下标
			if (equalIndex > 0) {
				const str = base64Str.substring(0, equalIndex); // 去除=号
				const strLength = str.length;
				const fileLength = strLength - (strLength / 8) * 2; // 真实的图片byte大小
				size = Math.floor(fileLength); // 向下取整
			} else {
				const strLength = base64Str.length;
				const fileLength = strLength - (strLength / 8) * 2;
				size = Math.floor(fileLength); // 向下取整
			}
		} else {
			size = null;
		}
		return size
	};
	import {
		forEach,
		indexOf,
		result
	} from 'lodash';
	export default {
		name: "upload-image",
		props: {
			/** 图片默认列表*/
			files: {
				type: Array
			},
			/** 是否禁用*/
			isdisabled: {
				type: Boolean,
				default: false
			},
			/**是否显示删除图片的按钮 */
			deletable: {
				type: Boolean,
				default: true
			}
		},
		data() {
			return {
				fileList1: [], //图片列表
				sizeType: ['compressed'],
				limitType: ['png', 'jpg', 'jpeg'], //允许的图片后缀
				fileMaxSize: 1 * 1024 * 1024, // 超出1M开启压缩
				maxSize:20 * 1024 * 1024, //图片最大不能超过20M
				fileMinSize: 5 * 1024 // 最小为5KB
			};
		},
		methods: {
			//文件大小超出限制
			oversize() {
				uni.showToast({
					title: "图片最大不能超过20M",
					icon: 'none'
				})
			},
			// 删除图片
			deletePic(event) {
				if (this.fileList1.length === 0) {
					this.files.splice(event.index, 1)
				} else {
					this[`fileList${event.name}`].splice(event.index, 1)
				}
				this.imgList(this.fileList1)
			},
			//点击图片触发
			clickPreview(url, lists, name) {
				console.log('点击预览：', url, lists, name);
			},
			/**获取文件大小倍数，生成质量比*/
			getCompressionRatio(fileSize) {
				const multiple = (fileSize / this.fileMaxSize).toFixed(2);
				let compressionRatio = 1;
				if (multiple > 5) {
					compressionRatio = 0.5
				} else if (multiple > 4) {
					compressionRatio = 0.6
				} else if (multiple > 3) {
					compressionRatio = 0.7
				} else if (multiple > 2) {
					compressionRatio = 0.8
				} else if (multiple > 1) {
					compressionRatio = 0.9
				} else {
					compressionRatio = 2
				}
				return compressionRatio;
			},
			// 读取图片
			async afterRead(event) {
				// 当设置 multiple 为 true 时, file 为数组格式，否则为对象格式
				let lists = [].concat(event.file);
				let fileListLen = this[`fileList${event.name}`].length;
				for (let index in lists) {
					const item = lists[index];
					const fileSize = item.size;
					const fileName = item.name ?? '';										
					if(!this.isAssetTypeAnImage(item.name)) {
						uni.showToast({
							title:'不允许该文件类型上传'
						})
						// this.$.msg('不允许该文件类型上传');						
						return false
					}
					console.log('文件大小',fileSize);					
					if (fileSize > this.fileMaxSize) {
						const compressionRatio = this.getCompressionRatio(fileSize);						
						if (compressionRatio > 1) {
							uni.showToast({
								title:'文件' + fileName + '大于10M'
							})
							// this.$.msg('文件' + fileName + '大于10M');
							return false
						}
						// 超出1M自动压缩图片
						await this.compressImg(item, compressionRatio)
						if (item.size > this.maxSize) {
							uni.showToast({
								title:'文件' + fileName + '压缩后超出20M'
							})
							// this.$.msg('文件' + fileName + '压缩后超出20M')
							return false
						}
					}
					if (item.size < this.fileMinSize) {
						// this.$.msg('文件' + fileName + '不能小于5KB');
						return false
					}					
					this[`fileList${event.name}`].push({
						...item,
						status: 'uploading',
						message: '上传中'
					})
				}
				for (let i = 0; i < lists.length; i++) {
					const result = await this.uploadFilePromise(lists[i].url); //调用上传图片的方法	
					console.log(result,111)
					if (!result.Success) {
						// uni.$showMsg(result.Message);
						const index = this.fileList1.findIndex(event => event.name === lists[i].name)
						if (index !== -1) return this.fileList1.splice(index, 1);
					}
					// 垃圾回收
					// window.URL.revokeObjectURL(lists[i].url);
					let item = this[`fileList${event.name}`][fileListLen]
					this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {
						status: 'success',
						message: '',
						url: lists[i].url,
						res: result
					}))
					fileListLen++
				}
				this.imgList(this.fileList1);
			},
			/** 压缩图片*/
			compressImg(source, compressionRatio) {
				let that = this;
				return new Promise((resolve, reject) => {
					compressImg(source.url, compressionRatio, source.type, compressRes => {
						resolve(compressRes);
					})
				}).then((res) => {
					source.size = res.size
					// window.URL.revokeObjectURL(source.url) // 删除被压缩的缓存文件,这里注意，如果是相册选择上传，可能会删除相册的图片
					source.url = res.source
					source.thumb = res.source					
					return source
				}).catch(err => {
					console.log('图片压缩失败', err)
				})
			},
 
			//父组件清空图片列表
			clearImgList() {
				this.fileList1 = []
			},
 
			//返回选择的图片列表
			imgList(list) {
				// console.log(list);
				let arr = []
				let newArr = []
				list.map(item => {
					arr.push(item.res)
				})
				arr.map(x => {
					newArr.push(x.Data[0])
				})
				this.$emit('imgList', Array.from(new Set(newArr)))
 
			},
		    /**判断文件类型是否正确 */
			isAssetTypeAnImage(ext) {
				const str = ext.split('.')[1];
				return this.limitType.indexOf(str.toLowerCase()) !== -1;			    
			},
 
			/**调用上传图片的接口 */
			uploadFilePromise(urls) {
				console.log(urls,222)
				return new Promise((resolve, reject) => {
					let a = uni.uploadFile({
						url: `${getApp().globalData.baseUrl}/api/common/upload`, // 仅为示例，非真实的接口地址
						filePath: urls,
						name: 'file',
						formData: {
							user: 'test'
						},
						success: (res) => {
							console.log(res,3333)
							setTimeout(() => {
								resolve(JSON.parse(res.data).data.fullurl)
							}, 1000)
						}
					});
				})
			},
		}
	}
</script>
 
<style lang="scss">
	image {
		width: 120rpx;
		height: 116rpx;
	}
</style>